package com.maple.blog.controller.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.maple.blog.bean.ArticleBean;
import com.maple.blog.bean.JianshuBean;
import com.maple.blog.bean.JianshuBean.*;
import com.maple.blog.config.JianshuConfig;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.stereotype.Service;

import java.beans.ConstructorProperties;
import java.io.IOException;
import java.util.List;

/**
 * 描述: com.maple.blog.controller.service
 *
 * @author hz.lei
 * @date 2018年04月27日 下午11:35
 */
@Service
public class JianshuService {
    private static final Logger log = LogManager.getLogger(JianshuService.class);
    private static final String USER_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1";
    private static final String PC_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36";
    private final JianshuConfig config;

    public JianshuBean parseUserAndBlogs() {
        JianshuBean jianshu = new JianshuBean();

        try {
            Document document = this.doGetHTML(this.userPageUri());
            this.parseUser(jianshu, document);
            String api = this.articlesJsonUri(jianshu.getAuthor().getUserId(), 1);
            JSONArray array = JSONObject.parseArray(this.doGetJSON(api));
            this.parseBlog(jianshu, array);
            JSONObject collections = JSONObject.parseObject(this.doGetJSON(this.collectionsJsonUri(1)));
            this.parseCollection(jianshu, collections);
            JSONObject notebooks = JSONObject.parseObject(this.doGetJSON(this.notebooksJsonUri(1)));
            this.parseNotebook(jianshu, notebooks);
        } catch (IOException e) {
            log.error("请求失败" + e.getMessage(), e);
        }

        return jianshu;
    }

    public JianshuBean parseNoteBooks(String id) {
        JianshuBean jianshu = new JianshuBean();

        try {
            Document document = this.doGetHTML(this.userPageUri());
            this.parseUser(jianshu, document);
            String api = this.notebookArticlesJsonUri(id, 1);
            JSONArray array = JSONObject.parseArray(this.doGetJSON(api));
            this.parseBlog(jianshu, array);
            JSONObject collections = JSONObject.parseObject(this.doGetJSON(this.collectionsJsonUri(1)));
            this.parseCollection(jianshu, collections);
            JSONObject notebooks = JSONObject.parseObject(this.doGetJSON(this.notebooksJsonUri(1)));
            this.parseNotebook(jianshu, notebooks);
        } catch (IOException e) {
            log.error("请求失败" + e.getMessage(), e);
        }

        return jianshu;
    }

    public JianshuBean parseCollections(String id) {
        JianshuBean jianshu = new JianshuBean();

        try {
            Document document = this.doGetHTML(this.userPageUri());
            this.parseUser(jianshu, document);
            String api = this.collectionArticlesJsonUri(id, 1);
            JSONArray array = JSONObject.parseArray(this.doGetJSON(api));
            this.parseBlog(jianshu, array);
            JSONObject collections = JSONObject.parseObject(this.doGetJSON(this.collectionsJsonUri(1)));
            this.parseCollection(jianshu, collections);
            JSONObject notebooks = JSONObject.parseObject(this.doGetJSON(this.notebooksJsonUri(1)));
            this.parseNotebook(jianshu, notebooks);
        } catch (IOException e) {
            log.error("请求失败" + e.getMessage(), e);
        }

        return jianshu;
    }

    public ArticleBean parseArticle(String articleId) {
        String api = "https://www.jianshu.com/p/" + articleId;
        ArticleBean article = new ArticleBean();

        try {
            Document document = Jsoup.connect(api).get();
            Element element = (Element) document.select("div.article").get(0);
            article.setTitle(element.select("h1.title").text());
            article.setAuthorAvatar(element.select("a.avatar img").attr("src"));
            article.setAuthorName(element.select("span.name a").text());
            article.setUpdateTime(element.select("span.publish-time").text());
            article.setWords(element.select("span.wordage").text());
            article.setContent(element.select("div.show-content").html().replaceAll("data-original-src", "src"));
        } catch (IOException e) {
            log.error("请求失败" + e.getMessage(), e);
        }

        return article;
    }

    public JianshuBean parseArticleList(int page) {
        JianshuBean jianshu = new JianshuBean();

        try {
            Document document = this.doGetHTML(this.userPageUri());
            this.parseUser(jianshu, document);
            String api = this.articlesJsonUri(jianshu.getAuthor().getUserId(), page);
            JSONArray array = JSONObject.parseArray(this.doGetJSON(api));
            this.parseBlog(jianshu, array);
        } catch (IOException e) {
            log.error("请求失败" + e.getMessage(), e);
        }

        return jianshu;
    }

    public JianshuBean parseArticleListInNotebook(String id, int page) {
        JianshuBean jianshu = new JianshuBean();

        try {
            String api = this.notebookArticlesJsonUri(id, page);
            JSONArray array = JSONObject.parseArray(this.doGetJSON(api));
            this.parseBlog(jianshu, array);
        } catch (IOException e) {
            log.error("请求失败" + e.getMessage(), e);
        }

        return jianshu;
    }

    public JianshuBean parseArticleListInCollection(String id, int page) {
        JianshuBean jianshu = new JianshuBean();

        try {
            String api = this.collectionArticlesJsonUri(id, page);
            JSONArray array = JSONObject.parseArray(this.doGetJSON(api));
            this.parseBlog(jianshu, array);
        } catch (IOException e) {
            log.error("请求失败" + e.getMessage(), e);
        }

        return jianshu;
    }

    public JianshuBean parseCollectionList(int page) {
        JianshuBean jianshu = new JianshuBean();

        try {
            JSONObject object = JSONObject.parseObject(this.doGetJSON(this.collectionsJsonUri(page)));
            this.parseCollection(jianshu, object);
        } catch (IOException e) {
            log.error("请求失败" + e.getMessage(), e);
        }

        return jianshu;
    }

    public JianshuBean parseNotebookList(int page) {
        JianshuBean jianshu = new JianshuBean();

        try {
            JSONObject object = JSONObject.parseObject(this.doGetJSON(this.notebooksJsonUri(page)));
            this.parseNotebook(jianshu, object);
        } catch (IOException e) {
            log.error("请求失败" + e.getMessage(), e);
        }

        return jianshu;
    }

    private void parseCollection(JianshuBean jianshu, JSONObject collections) {
        jianshu.setOwnCollectionPage(collections.getIntValue("page"));
        jianshu.setOwnCollectionTotalPages(collections.getIntValue("total_pages"));
        JSONArray array = collections.getJSONArray("collections");

        for (int i = 0; i < array.size(); ++i) {
            OwnCollection collection = new OwnCollection();

            JSONObject object = array.getJSONObject(i);
            collection.setAvatar(object.getString("avatar").replace("http:", ""));
            collection.setId(object.getString("id"));
            collection.setSlug(object.getString("slug"));
            collection.setTitle(object.getString("title"));
            jianshu.getOwnCollections().add(collection);
        }

    }

    private void parseNotebook(JianshuBean jianshu, JSONObject notebooks) {
        jianshu.setNotebookPage(notebooks.getIntValue("page"));
        jianshu.setNotebookTotalPages(notebooks.getIntValue("total_pages"));
        JSONArray array = notebooks.getJSONArray("notebooks");

        for (int i = 0; i < array.size(); ++i) {
            JianshuBean.Notebook notebook = new JianshuBean.Notebook();
            JSONObject object = array.getJSONObject(i);
            notebook.setBook(object.getBoolean("book"));
            notebook.setId(object.getString("id"));
            notebook.setName(object.getString("name"));
            jianshu.getNotebooks().add(notebook);
        }

    }

    private void parseUser(JianshuBean jianshu, Document document) {
        Author author = jianshu.getAuthor();
        String avatar = document.select("a.avatar img").attr("src");
        author.setAvatar(avatar);
        String nickname = document.select("a.name").text();
        author.setNickname(nickname);
        String description = document.select("div.js-intro").text();
        author.setDescription(description);
        String userId = document.select("div.follow-button").attr("props-data-user-id");
        author.setUserId(userId);
    }

    private void parseBlog(JianshuBean jianshu, JSONArray array) {
        List<JianshuBean.Article> articles = jianshu.getArticles();

        for (int i = 0; i < array.size(); ++i) {
            JSONObject object = array.getJSONObject(i).getJSONObject("object").getJSONObject("data");
            JianshuBean.Article article = new JianshuBean.Article();
            article.setCover(object.getString("list_image_url").replace("http:", ""));
            article.setDescription(object.getString("public_abbr"));
            article.setTitle(object.getString("title"));
            article.setLikeCount(object.getInteger("likes_count"));
            String time = object.getString("first_shared_at");
            article.setTime(this.handleTime(time));
            article.setId(object.getString("slug"));
            articles.add(article);
        }

    }

    private String userPageUri() {
        return "https://www.jianshu.com/u/" + this.config.getUserId();
    }

    private String articlesJsonUri(String userId, int page) {
        return "https://www.jianshu.com/mobile/users/" + userId + "/public_notes?page=" + page + "&count=10";
    }

    private String notebookArticlesJsonUri(String id, int page) {
        return "https://www.jianshu.com/mobile/notebooks/" + id + "/public_notes?page=" + page + "&count=10";
    }

    private String collectionArticlesJsonUri(String id, int page) {
        return "https://www.jianshu.com/mobile/collections/" + id + "/public_notes?page=" + page + "&count=10";
    }

    private String notebooksJsonUri(int page) {
        return "https://www.jianshu.com/users/" + this.config.getUserId() + "/notebooks?slug=" + this.config.getUserId() + "&type=manager&page=" + page + "&per_page=10";
    }

    private String collectionsJsonUri(int page) {
        return "https://www.jianshu.com/users/" + this.config.getUserId() + "/collections?slug=" + this.config.getUserId() + "&type=own&page=" + page + "&per_page=10";
    }

    private String handleTime(String time) {
        time = time.replace("T", " ");
        return time.substring(0, 19);
    }

    private Document doGetHTML(String url) throws IOException {
        return Jsoup.connect(url).header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36").ignoreContentType(true).validateTLSCertificates(false).get();
    }

    private String doGetJSON(String url) throws IOException {
        return Jsoup.connect(url).header("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1").header("Accept", "application/json").ignoreContentType(true).validateTLSCertificates(false).get().text();
    }

    @ConstructorProperties({"config"})
    public JianshuService(final JianshuConfig config) {
        this.config = config;
    }
}
